#ifndef _DEBUG_STREAM_H_
#define _DEBUG_STREAM_H_

#include "DebugBuffer.h"

template
<
    class charT,                                // character type 
    class logfunction,                          // logfunction type
    class traits = std::char_traits<charT>      // character traits 
>
class cDebugStream : public std::basic_ostream<charT, traits>
{
	typedef std::basic_string<charT, traits> cStringType;
	typedef cDebugBuffer<charT, logfunction, traits> cBufferType;
	typedef std::basic_ostream<charT, traits> cStreamType;                  
	typedef std::basic_ostringstream<charT, traits> cStringStreamType;
public:
    cDebugStream(const char *lacFile = 0, int liLine = -1)
		: cStreamType(&mBuffer), macFile(lacFile), miLine(liLine)
    {
        BuildContext(); // build the whole context and set it to the streambuffer
    }
    cDebugStream(const cStringType &lContext, const char *lacFile = 0, int liLine = -1)
		: cStreamType(&mBuffer), macFile(lacFile), miLine(liLine), mContext(lContext)
    {
        BuildContext(); // build the whole context and set it to the streambuffer
    }
	virtual ~cDebugStream() {};
    void SetContext(const cStringType &lContext)
	{
		mContext = lContext;
		BuildContext();
	}
	const cStringType GetContext() const { return mContext; }
    cDebugStream &Get() {return *this;}
private:
    cDebugStream(const cDebugStream &);
    cDebugStream &operator=(const cDebugStream &);
    void BuildContext()
	{
		cStringStreamType os;			// format the prefix via stringstream 

        if (macFile)                      // if a filename is given
            os << macFile;                // show it first
        if (miLine >= 0)                 // if a linenumber is given
			os << "(" << miLine << ")";  // show it in brackets
        if (macFile || miLine >= 0)        // if filename or linenumber given
            os << " : ";                // separate it by a double colon from context or message
        if (!mContext.empty())          // if a context string is given
            os << mContext << " : ";    // show it at last separate it by a double colon from the message
        mBuffer.SetContext(os.str());      // set the context to the streambuffer
    }
    const char *macFile;    
    const int miLine;
    cStringType mContext;
    cBufferType mBuffer;
};

#endif